package com.dkd.service.impl;

import cn.elegent.token.dto.RefreshDTO;
import cn.elegent.token.dto.TokenDTO;
import cn.elegent.token.refresh.service.CustomService;
import cn.elegent.util.json.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * RefreshTokenServiceImpl
 * @author: wgl
 * @describe: 刷新Token拓展实现策略
 * 需要实现每个刷新token只能使用一次
 */
@ConditionalOnProperty(prefix = "elegent.token.custom", name = "check", havingValue = "one")
@Service
public class RefreshTokenServiceImpl implements CustomService {
	
	private final static String tokenKey = "refreshToken:";
	
	private final static String userIdKey = "userId";
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	/**
	 * 用于校验刷新token
	 * @param user
	 * @return
	 */
	@Override
	public Boolean checkRefreshToken(String refreshToken, Object user) {
		String redisKey = getRedisKey(user);
		//如果刷新token在redis中存在  并且当前redis中的刷新token就是传入的刷新token
		if ((redisTemplate.opsForValue().get(redisKey) != null) && (refreshToken.equals(redisTemplate.opsForValue().get(redisKey)))) {
			//表明本次请求刷新token是被允许的 将原有的redis的key删除
			redisTemplate.delete(redisKey);
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 记录刷新token到Redis中
	 * @param accessToken
	 * @param refreshToken
	 */
	@Override
	public void customHook(TokenDTO accessToken, TokenDTO refreshToken, Object user) {
		String redisKey = getRedisKey(user);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			//计算相差多少秒
			Long secDiff = dateDiff(new Date(), sdf.parse(refreshToken.getLifespan()));
			redisTemplate.opsForValue().set(redisKey, refreshToken.getToken(), secDiff, TimeUnit.SECONDS);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 在重新生成刷新token之后将刷新token存入redis中
	 * @param refreshDTO
	 * @param user
	 */
	@Override
	public void afterRefreshHook(RefreshDTO refreshDTO, Object user) {
		String redisKey = getRedisKey(user);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			//计算相差多少秒
			Long secDiff = dateDiff(new Date(), sdf.parse(refreshDTO.getRefreshToken().getLifespan()));
			redisTemplate.opsForValue().set(redisKey, refreshDTO.getRefreshToken().getToken(), secDiff, TimeUnit.SECONDS);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/**
	 * 根据框架提供的用户对象获取redis里的key
	 * @param user
	 * @return
	 */
	private String getRedisKey(Object user) {
		String redisKey = null;
		try {
			Map<String, Object> payLoadMap = JsonUtil.convertToMap(user);
			redisKey = tokenKey + payLoadMap.get(userIdKey);
			return redisKey;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 计算2个时间相差的天数、小时、分钟、秒
	 * @param startTime 开始时间
	 * @param endTime   截止时间
	 * @return
	 */
	public static Long dateDiff(Date startTime, Date endTime) {
		long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
		long nh = 1000 * 60 * 60;// 一小时的毫秒数
		long nm = 1000 * 60;// 一分钟的毫秒数
		long ns = 1000;// 一秒钟的毫秒数
		long diff;
		long second = 0;
		// 获得两个时间的毫秒时间差异
		try {
			diff = endTime.getTime() - startTime.getTime();
			// 计算差多少秒
			second = diff / ns;
			// 输出结果
			/*System.out.println("hour=" + hour + ",min=" + min);*/
		} catch (Exception e) {
			e.printStackTrace();
		}
		return second;
	}
}
